home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / sticpsrc.lzh / SOURCE.ARC / PC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-21  |  14.0 KB  |  634 lines

  1. /* OS- and machine-dependent stuff for IBM-PC running MS-DOS */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5.  
  6. #if (defined(MSC) || defined(__TURBOC__))
  7. # include <process.h>
  8. # include <signal.h>
  9. # ifdef MSC
  10. #  include <malloc.h>
  11.    void (*getvect())();
  12. # endif
  13. #else
  14. # ifdef RAWCON
  15. #  include <sgtty.h>
  16. # endif
  17. #endif
  18.  
  19. #include "global.h"
  20. #include "config.h"
  21. #include "mbuf.h"
  22. #include "internet.h"
  23. #include "iface.h"
  24. #include "cmdparse.h"
  25. #include "timer.h"
  26. #include "environ.h"
  27.  
  28. /* Interface list header */
  29. struct interface *ifaces;
  30.  
  31. #if (!defined(MSC) && !defined(__TURBOC__))
  32. /* Aztec memory allocation control */
  33. int _STKLOW = 0;    /* Stack above heap */
  34. int _STKSIZ = 4096/16;    /* 4K stack -- overridden in grabcore */
  35. int _HEAPSIZ = 4096/16; /* Isn't really used */
  36. int _STKRED = 4096;    /* Stack red zone in bytes -- this really matters */
  37. #endif
  38.  
  39. char ttbuf[BUFSIZ];
  40.  
  41. #ifdef SERVERS
  42. extern FILE *logfp;            /* log file pointer */
  43. extern char logname[];            /* log file name */
  44. #endif
  45.  
  46. #ifdef TRACE
  47. extern FILE *trfp;            /* trace file pointer */
  48. extern char trname[];            /* trace file name */
  49. #endif
  50.  
  51. static unsigned watchhw;        /* watchdog hardware reset value */
  52. static unsigned watchport;        /* watchdog output port number */
  53.  
  54. #if (defined(MSC) || defined(__TURBOC__))
  55. /* critical error handler stuff - will fail system calls all the time */
  56.  
  57. void (*orgcritvect)(void);
  58. extern void crit_hdl(void);
  59.  
  60. void crit_remove (void)
  61.  
  62. {
  63.     setvect(0x24,orgcritvect);
  64. }
  65. #endif
  66.  
  67. /* Called at startup time to set up console I/O, memory heap */
  68. ioinit()
  69. {
  70. #if (!defined(MSC) && !defined(__TURBOC__))
  71. # ifdef RAWCON
  72.     struct sgttyb ttybuf;
  73. # endif
  74. #endif
  75.  
  76.     /* Save these file table entries for something more useful */
  77.     /* PE1CHL: this seems to cause problems so let's skip it for awhile */
  78. #ifdef CLOSEDEVS
  79. # ifdef stdaux
  80.     fclose(stdaux);
  81. # endif
  82. # ifdef stdprn
  83.     fclose(stdprn);
  84. # endif
  85. # ifdef stdprt
  86.     fclose(stdprt);
  87. # endif
  88. #endif
  89.  
  90. #if (!defined(MSC))
  91.     /* Interrupts use a special stack deep in data space.
  92.      * Calls to sbrk() (invoked by malloc when it needs more memory
  93.      * from the system) at interrupt time will fail because sbrk()
  94.      * will think that the stack has overwritten the heap. So
  95.      * grab all the memory we can now for the heap so that malloc
  96.      * won't have to call sbrk and alloc_mbuf() won't fail unnecessarily
  97.      * at interrupt time.
  98.      */
  99.     grabcore();
  100. #endif
  101.  
  102.     setbuf(stdout,ttbuf);
  103.  
  104. #if (defined(MSC) || defined(__TURBOC__))
  105.     signal(SIGINT,SIG_IGN);        /* don't like killing NET */
  106. #else
  107. # ifdef RAWCON
  108.     /* Put display in raw mode. Note that this breaks tab expansion,
  109.      * so you need to run NANSI.SYS or equivalent.
  110.      */
  111.     ioctl(1,TIOCGETP,&ttybuf);
  112.     ttybuf.sg_flags = RAW;
  113.     ioctl(1,TIOCSETP,&ttybuf);
  114. # endif
  115. #endif
  116.  
  117. #if (defined(MSC) || defined(__TURBOC__))
  118.     orgcritvect = getvect(0x24);
  119.     setvect(0x24,crit_hdl);
  120.     atexit(crit_remove);
  121. #endif
  122. }
  123. /* Called just before exiting to restore console state */
  124. iostop()
  125. {
  126. #if (!defined(MSC) && !defined(__TURBOC__))
  127. # ifdef RAWCON
  128.     struct sgttyb ttybuf;
  129. # endif
  130. #endif
  131.  
  132. #if (!defined(MSC) && !defined(__TURBOC__))
  133. # ifdef RAWCON
  134.     ioctl(1,TIOCGETP,&ttybuf);
  135.     ttybuf.sg_flags &= ~RAW;
  136.     ioctl(1,TIOCSETP,&ttybuf);
  137. # endif
  138. #endif
  139.     while(ifaces != NULLIF){
  140.         /* first flush the interface's buffers */
  141.         while(ifaces->recv != NULLFP && (*ifaces->recv)(ifaces))
  142.             ;
  143.         if(ifaces->stop != NULLFP)
  144.             (*ifaces->stop)(ifaces);
  145.         ifaces = ifaces->next;
  146.     }
  147. }
  148.  
  149. /* Print or Set the date and time */
  150.  
  151. dodate(argc,argv)
  152.     int argc;
  153.     char *argv[];
  154. {
  155.     long tloc;
  156.     register char *p;
  157. #ifdef    MSC
  158.     struct dosdate_t dosdate;
  159.     struct dostime_t dostime;
  160. #endif
  161. #ifdef    __TURBOC__
  162.     struct date dosdate;
  163.     struct time dostime;
  164. #endif
  165.  
  166.     if (argc < 2) {
  167.         time(&tloc);
  168.         printf("%s",ctime(&tloc));
  169.         return 0;
  170.     }
  171.  
  172. #if (defined(MSC) || defined(__TURBOC__))
  173.     p = argv[1];
  174.  
  175.     if (strlen(p) != 10 && strlen(p) != 12)
  176.         return -1;
  177.     while (*p)
  178.         if (!isdigit(*p++))
  179.         return -1;
  180.  
  181. # ifdef    MSC
  182.     _dos_getdate(&dosdate);            /* read the year */
  183.     p = argv[1];
  184.     dosdate.month = 10 * p[0] + p[1] - 11 * '0';
  185.     dosdate.day = 10 * p[2] + p[3] - 11 * '0';
  186.     dostime.hour = 10 * p[4] + p[5] - 11 * '0';
  187.     dostime.minute = 10 * p[6] + p[7] - 11 * '0';
  188.     dostime.second = 10 * p[8] + p[9] - 11 * '0';
  189.     if (p[10]) {
  190.         if ((dosdate.year = 10 * p[10] + p[11] - 11 * '0' + 1900) < 1980)
  191.         dosdate.year += 100;
  192.     }
  193.     dostime.hsecond = 0;
  194.  
  195.     if (_dos_settime(&dostime) || _dos_setdate(&dosdate))
  196.         return -1;
  197. # endif
  198. # ifdef    __TURBOC__
  199.     getdate(&dosdate);            /* read the year */
  200.     p = argv[1];
  201.     dosdate.da_mon = 10 * p[0] + p[1] - 11 * '0';
  202.     dosdate.da_day = 10 * p[2] + p[3] - 11 * '0';
  203.     dostime.ti_hour = 10 * p[4] + p[5] - 11 * '0';
  204.     dostime.ti_min = 10 * p[6] + p[7] - 11 * '0';
  205.     dostime.ti_sec = 10 * p[8] + p[9] - 11 * '0';
  206.     if (p[10]) {
  207.         if ((dosdate.da_year = 10 * p[10] + p[11] - 11 * '0' + 1900) < 1980)
  208.         dosdate.da_year += 100;
  209.     }
  210.     dostime.ti_hund = 0;
  211.  
  212.     settime(&dostime);
  213.     setdate(&dosdate);
  214. # endif
  215. #else
  216.     printf("Date/Time setting not supported in this version!\n");
  217. #endif
  218.  
  219.     return 0;
  220. }
  221.  
  222. /* Spawn subshell */
  223. doshell(argc,argv)
  224. int argc;
  225. char *argv[];
  226.  
  227. {
  228.     char *command,**envp;
  229.     int ret;
  230. #ifdef MSDOS
  231.     unsigned short envseg;
  232. #endif
  233. #if (!defined(MSC) && !defined(__TURBOC__))
  234. # ifdef RAWCON
  235.     struct sgttyb ttybuf,ttysav;
  236.  
  237.     ioctl(1,TIOCGETP,&ttysav);
  238.     ioctl(1,TIOCGETP,&ttybuf);
  239.     ttybuf.sg_flags &= ~RAW;
  240.     ioctl(1,TIOCSETP,&ttybuf);
  241. # endif
  242. #endif
  243.  
  244.     if((command = getenv("COMSPEC")) == NULLCHAR)
  245.         command = "/COMMAND.COM";
  246.  
  247. #ifdef SERVERS
  248.     if (logfp != NULLFILE)        /* logging to file? */
  249.         fclose(logfp);
  250. #endif
  251.  
  252. #ifdef TRACE
  253.     if (trfp != stdout)        /* trace to file? */
  254.         fclose(trfp);        /* close it during shell exec */
  255. #endif
  256.  
  257.     envp = make_env();        /* create env, starts on PARA bound */
  258.  
  259. #if (defined(MSC) || defined(__TURBOC__))
  260.     ret = spawnve(P_WAIT,command,&argv[0],envp);
  261. #else
  262.     if (envp != NULLCHRP)        /* could the env be allocated? */
  263.         envseg = getds() + (((unsigned) envp[0]) >> 4); /* get segment addr of env */
  264.     else
  265.         envseg = 0;            /* no space, pass our own env */
  266.  
  267.     ret = fexecve(command,&argv[0],envseg);
  268. # ifdef RAWCON
  269.     ioctl(1,TIOCSETP,&ttysav);
  270. # endif
  271. #endif
  272.  
  273.     free_env();            /* free the envp and temp env */
  274.  
  275. #ifdef SERVERS
  276.     if (logfp != NULLFILE)        /* re-open logfile if it was open */
  277.         logfp = fopen(logname,"a+");
  278. #endif
  279.  
  280. #ifdef TRACE
  281.     if (trfp != stdout)        /* re-open tracefile if not stdout */
  282.         if ((trfp = fopen(trname,"a+")) == NULLFILE)
  283.         trfp = stdout;
  284. #endif
  285.  
  286.     if (ret != 0)
  287.         return -1;
  288.  
  289. #if (defined(MSC) || defined(__TURBOC__))
  290.     return 0;
  291. #else
  292.     return wait();
  293. #endif
  294. }
  295.  
  296. #if (!defined(MSC) && !defined(__TURBOC__))
  297. /* the following piece of code was taken from the Aztec 4.10 runtime */
  298. /* source for fexecv() and slightly adapted to pass the environment */
  299. /* to the executed program. */
  300. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  301.  
  302. fexecve(path, argv, env)
  303. char *path, **argv;
  304. unsigned short env;
  305. {
  306.     register char *cp, *xp;
  307.     int i;
  308.     char buffer[130];
  309.     char fcb1[16], fcb2[16];
  310.  
  311.     cp = buffer+1;
  312.     i = 1;
  313.     fcbinit(".", fcb1);        /* initialize fcb's, in case no args */
  314.     fcbinit(".", fcb2);
  315.     if (*argv) {
  316.         ++argv;            /* skip arg0, used for unix (tm) compatibility */
  317.         while ((xp = *argv++) != '\0') {
  318.             if (i == 1)
  319.                 fcbinit(xp, fcb1);
  320.             else if (i == 2)
  321.                 fcbinit(xp, fcb2);
  322.             *cp++ = ' ';
  323.             while (*xp) {
  324.                 if (cp >= buffer+127)
  325.                     goto done;
  326.                 *cp++ = *xp++;
  327.             }
  328.             ++i;
  329.         }
  330.     }
  331. done:
  332.     buffer[0] = cp - (buffer+1);
  333.     *cp = '\r';        /* add CR to make some dos commands happy */
  334.     return fexec(path, env, buffer, fcb1, fcb2);
  335. }
  336. #endif
  337.  
  338. /* checks the time then ticks and updates ISS */
  339. static short clockstart = 0;
  340. static int32 clkval = 0;
  341. void
  342. check_time()
  343. {
  344.     int32 iss();
  345.     int32 ntime;
  346.     int maxticks = SEC2TICK(15);    /* upper limit on delayed ticks */
  347.     char i_state;
  348. #if (defined(MSC) || defined(__TURBOC__))
  349. # define peekw(off,seg) (*((unsigned far*) (((long) (seg) << 16) | (off))))
  350. #else
  351.     extern int16 peekw();
  352. #endif
  353.  
  354.     if(!clockstart){
  355.         /* Executed only once */
  356.         i_state = disable();
  357.         clkval = ((int32) peekw(0x6e,0x40) << 16) | peekw(0x6c,0x40);
  358.         restore(i_state);
  359.         clockstart = 1;
  360.         return;
  361.     }
  362.     /* set the "watchhw" bit of "watchport" (when it is defined) */
  363.     if (watchhw)
  364.         outportb(watchport,inportb(watchport) | watchhw);
  365.  
  366.     /* Read the low order word of the BIOS tick counter directly. The
  367.      * INT 1Ah call isn't used because it stupidly clears the
  368.      * "midnight passed" flag and we'd have to update the date ourselves.
  369.      * (See Norton, p222).
  370.      *
  371.      * The PC's time-of-day handling is a real crock of shit. Why not a
  372.      * nice simple long binary count from a fixed UTC epoch, as in UNIX??
  373.      */
  374.     i_state = disable();
  375.     ntime = ((int32) peekw(0x6e,0x40) << 16) | peekw(0x6c,0x40);
  376.     restore(i_state);
  377.  
  378.     /* separately check for time-of-day rollover to prevent strange
  379.      * behaviour of the timers at midnight...
  380.      */
  381.     if (ntime < clkval){
  382.         clkval -= 1573040L;        /* counts per day */
  383.     }
  384.  
  385.     while(ntime != clkval){ /* Handle possibility of several missed ticks */
  386. #ifdef IP
  387.         icmpclk();    /* Call this one before tick */
  388. #endif
  389.         tick();
  390. #ifdef IP
  391.         (void)iss();
  392. #endif
  393.         if(maxticks--)    /* check limit on ticks to handle */
  394.             clkval++;
  395.         else
  396.             clkval = ntime; /* ignore any remaining ticks */
  397.     }
  398.     /* clear the "watchhw" bit of "watchport" (when it is defined) */
  399.     if (watchhw)
  400.         outportb(watchport,inportb(watchport) & ~watchhw);
  401. }
  402. /* Read characters from the keyboard, translating them to "real" ASCII
  403.  * If none are ready, return the -1 from kbraw()
  404.  */
  405. int
  406. kbread()
  407. {
  408.     int kbraw(),c;
  409.  
  410.     if((c = kbraw()) == 0){
  411.         /* Lead-in to a special char */
  412.         c = kbread();
  413.         switch(c){
  414.         case 3:        /* NULL (bizzare!) */
  415.             c = 0;
  416.             break;
  417.         case 59:    /* F-1 key */
  418.             c = -11;
  419.             break;
  420.         case 60:    /* F-2 key */
  421.             c = -10;
  422.             break;
  423.         case 61:    /* F-3 key */
  424.             c = -9;
  425.             break;
  426.         case 62:    /* F-4 key */
  427.             c = -8;
  428.             break;
  429.         case 63:    /* F-5 key */
  430.             c = -7;
  431.             break;
  432.         case 64:    /* F-6 key */
  433.             c = -6;
  434.             break;
  435.         case 65:    /* F-7 key */
  436.             c = -5;
  437.             break;
  438.         case 66:    /* F-8 key */
  439.             c = -4;
  440.             break;
  441.         case 67:    /* F-9 key */
  442.             c = -3;
  443.             break;
  444.         case 68:    /* F-10 key (used as command-mode escape) */
  445.             c = -2;
  446.             break;
  447.         case 71:    /* HOME key */
  448.             c = -20;
  449.             break;
  450.         case 72:    /* UP arrow */
  451.             c = -19;
  452.             break;
  453.         case 73:    /* PAGE UP */
  454.             c = -18;
  455.             break;
  456.         case 75:    /* LEFT arrow */
  457.             c = -17;
  458.             break;
  459.         case 77:    /* RIGHT arrow */
  460.             c = -16;
  461.             break;
  462.         case 79:    /* END key */
  463.             c = -15;
  464.             break;
  465.         case 80:    /* DOWN arrow */
  466.             c = -14;
  467.             break;
  468.         case 81:    /* PAGE DOWN */
  469.             c = -13;
  470.             break;
  471.         case 82:    /* INS key */
  472.             c = -12;
  473.             break;
  474.         case 83:    /* DEL key */
  475.             c = 0x7f;
  476.             break;
  477.         default:    /* Dunno what it is */
  478.             c = -1;
  479.         }
  480.     }
  481.     return c;
  482. }
  483.  
  484. #if (!defined(MSC) && !defined(__TURBOC__))
  485. #define CTLZ    26
  486. /* Special version of aputc() (used by putchar and printf) that filters
  487.  * out nasty characters that screw up the DDOS and ANSI terminal drivers
  488.  * Also, it facilitates re-routing of standard output to an alternative
  489.  * handler, e.g. to send it via TCP.
  490.  */
  491. int (*put_stdout)() = (int (*)()) 0;
  492. int
  493. aputc(c,file)
  494. int c;
  495. FILE *file;
  496. {
  497.     if(file == stdout){
  498.         /* Nulls get displayed as spaces by ansi.sys (wrong)
  499.          * ^Z's seem to hang the DoubleDos and DesqView screen drivers
  500.          */
  501.         if((c == '\0' || c == CTLZ))
  502.             return c;
  503.  
  504.         /* Check for presence of alternative putc function
  505.          */
  506.         if(put_stdout != (int (*)()) 0)
  507.             return (*put_stdout)(c,file);
  508.     }
  509.     /* Do end-of-line translations */
  510.     if(c == '\n')
  511.         putc('\r',file);
  512.     return putc(c,file);
  513. }
  514. #endif
  515.  
  516. /* Reset the CPU, reboot DOS */
  517. sysreset()
  518. {
  519.     void (*reset)();        /* just a pointer to function */
  520.  
  521.     reset = (void (*)()) 0xffff0000; /* point to reset location */
  522.     (*reset)();            /* and call it */
  523. }
  524.  
  525. #if (!defined(LARGEDATA))
  526. /* Convert a pointer to a long integer, so that it can be printed in a
  527.    compiler- and system-independent way.
  528.    This function currently assumes that pointers are 16-bit (int) size.
  529.  */
  530. long ptr2long (p)
  531. char *p;
  532. {
  533.     unsigned int rv = (unsigned int) p;
  534.  
  535.     return (long) rv;
  536. }
  537. #endif
  538.  
  539. #ifdef __TURBOC__
  540. /* the strrchr() function is broken in Turbo C 2.0 */
  541. /* this implementation is probably more efficient, too... */
  542.  
  543. char *strrchr (const char *s, int c)
  544.  
  545. {
  546.     register char *rv = NULL;            /* return value */
  547.  
  548.     do
  549.     {
  550.     if (*s == (char) c)            /* a match here? */
  551.         rv = (char *) s;            /* remember it */
  552.     }
  553.     while (*s++);
  554.  
  555.     return rv;                    /* return last match or NULL */
  556. }
  557. #endif
  558.  
  559. #ifdef MSC
  560. int memstat (argc,argv)
  561. int argc;
  562. char *argv[];
  563.  
  564. {
  565. #ifdef SHOWHEAP
  566.     unsigned long used;
  567.     struct heapinfo {
  568.         int far *pentry;
  569.         size_t size;
  570.         int useflag;
  571.     } hinfo;
  572. #endif
  573.     int _heapset();
  574. #ifndef LARGEDATA
  575.     unsigned int _memavl(),_memmax();
  576. #endif
  577.  
  578. #ifdef SHOWHEAP
  579.     if (argc > 1){
  580.         used = 0;
  581.         hinfo.pentry = NULL;
  582.         while (_heapwalk(&hinfo) == _HEAPOK) {
  583.         switch (hinfo.useflag)
  584.         {
  585.         case _FREEENTRY:
  586.             printf("%8u",hinfo.size);
  587.             break;
  588.         case _USEDENTRY:
  589.             used += hinfo.size;
  590.             break;
  591.         }
  592.         }
  593.         printf("\n%lu bytes used, ",used);
  594.     }
  595. #endif
  596.  
  597. #ifdef LARGEDATA
  598.     printf("heap %s\n",(_heapset(0) == _HEAPOK)? "okay":"BAD");
  599. #else
  600.     printf("%u bytes available, largest block %u bytes, heap %s\n",
  601.            _memavl(),_memmax(),(_heapset(0) == _HEAPOK)? "okay":"BAD");
  602. #endif
  603.  
  604.     return 0;
  605. }
  606. #endif
  607.  
  608. /* control the watchdog function */
  609.  
  610. int
  611. dowatchdog (argc,argv)
  612.     int argc;
  613.     char *argv[];
  614. {
  615.     switch (argc)
  616.     {
  617.     case 3:
  618.         watchhw = htoi(argv[2]) & 0xff;
  619.     case 2:
  620.         if ((watchport = htoi(argv[1])) == 0) {
  621.             printf("Usage: %s [<port> <value>]\n",argv[0]);
  622.             watchhw = 0;
  623.         }
  624.         break;
  625.     case 1:
  626.         if (watchhw)
  627.             printf("PORT=%04x VALUE=%02x\n",watchport,watchhw);
  628.         else
  629.             printf("OFF\n");
  630.         break;
  631.     }
  632.     return 0;
  633. }
  634.